//    Copyright (C) Kherty.  All rights reserved.
#region

using System.Collections.Generic;
using System.Diagnostics.Contracts;
using OpenLS.Core.Serialization;

#endregion

namespace OpenLS.Spreadsheet
{
    internal class SharedStrings : IOfficeXmlSerializable
    {
        private const string xmlName = "sst";
        private readonly List<object> _uniqueItems = new List<object>();
        public IEnumerable<object> GetUniqueItems()
        {
            return _uniqueItems;
        }
        private Dictionary<object, int> _backTable;
        private int _nonUniqueCount;

        public object this[int i]
        {
            get
            {
                Contract.Requires(i >= 0);

                return _uniqueItems[i];
            }
        }

        public int Count
        {
            get { return _uniqueItems.Count; }
        }

        #region IOfficeXmlSerializable Members

        void IOfficeXmlSerializable.ReadXml(ReadContext context)
        {
            using (var c = context.Read(xmlName))
            {
                _nonUniqueCount = c.GetOptionalInteger("count", 0);
                while (c.ReaderLocalName == "si")
                {
                    using (var c2 = c.Read("si"))
                    {
                        if (c2.ReaderLocalName == "t")
                        {
                            var s = XmlStringHelper.Decode(c2.ReadElementString("t"));
                            _uniqueItems.Add(s);
                        }
                        else
                        {
                            var para = new RichTextParagraph();
                            while (c2.ReaderLocalName == "r")
                            {
                                para.Runs.Add(c2.ReadElement<RichTextRun>());
                            }
                            _uniqueItems.Add(para);
                        }
                        while (c2.ReaderLocalName == "rPh") //\\
                            c2.EatForNow("rPh");
                        c2.EatForNow("phoneticPr");
                    }
                }
            }
        }

        void IOfficeXmlSerializable.WriteXml(WriteContext context)
        {
            using (var c = context.Write(xmlName))
            {
                // c.SetInteger("uniqueCount", uniqueItems.Count);
                // c.SetInteger("count", nonUniqueCount);
                foreach (var s in _uniqueItems)
                {
                    if (s is string)
                    {
                        using (var sstItem = c.Write("si"))
                        {
                            using (var t = sstItem.Write("t"))
                            {
                                
                                t.WritePreservedString(XmlStringHelper.Encode((string) s));
                            }
                        }
                    }
                    else
                    {
                        var p = (RichTextParagraph) s;
                        c.WriteElementAs(p, "si");
                    }
                }
            }
        }

        #endregion

        /// <summary>
        /// Custom data serialization
        /// </summary>
        /// <param name="s"></param>
        public void AddCustomData(string s)
        {
            _uniqueItems.Add(s);
        }

        internal int GetIndex(object s) //\\inefficient
        {
            ensureBackTable();
            int result;
            if (_backTable.TryGetValue(s, out result))
                return result;
            //for (int i = 0; i < uniqueItems.Count; i++)
            //  if (uniqueItems[i] == s)
            //    return i;
            _uniqueItems.Add(s);

            _nonUniqueCount++;
            result = _uniqueItems.Count - 1;
            _backTable.Add(s, result);
            return result;
        }

        private void ensureBackTable()
        {
            if (_backTable == null)
            {
                _backTable = new Dictionary<object, int>();
                for (var i = 0; i < _uniqueItems.Count; i++)
                {
                    _backTable.Add(_uniqueItems[i], i);
                }
            }
        }
    }

    public class SharedString
    {
        public string Value { get; set; }
    }
}